#pragma once

#include "ThreadCache.h"
#include "PageCache.h"
#include "ObjectPool.h"

static void* ConcurrentAlloc(size_t size)
{
	assert(size > 0);

	if (size > MAX_SIZE)
	{
		size_t alignsize = SizeClass::AlignUp(size);
		size_t k = (alignsize >> PAGE_SHIFT);

		PageCache::GetPageSingleton()->GetGlobalMutex().lock();

		Span* span = PageCache::GetPageSingleton()->NewSpan(k);
		span->_isusing = true;
		span->_objsize = alignsize;

		PageCache::GetPageSingleton()->GetGlobalMutex().unlock();
		return (void*)(span->_id << PAGE_SHIFT);
	}
	else
	{
		if (pThreadCache == nullptr)
		{
			//pThreadCache = new ThreadCache;
			static ObjectPool<ThreadCache> pool;
			pThreadCache = pool.New();
		}

		return pThreadCache->Allocate(size);
	}
}

static void ConcurrentFree(void* ptr)
{
	assert(ptr);

	Span* span = PageCache::GetPageSingleton()->PageId_To_Span(ptr);
	size_t alignsize = span->_objsize;
	if (alignsize > MAX_SIZE)
	{

		PageCache::GetPageSingleton()->GetGlobalMutex().lock();

		PageCache::GetPageSingleton()->ReleaseToPageCache(span);

		PageCache::GetPageSingleton()->GetGlobalMutex().unlock();
		return;
	}

	assert(pThreadCache);
	assert(alignsize <= MAX_SIZE);

	pThreadCache->ReleaseToThreadCache(ptr, alignsize);
}